package com.animerank.service.impl;

import com.animerank.dto.Result;
import com.animerank.service.IDoubanService;
import com.dtflys.forest.annotation.Request;
import com.dtflys.forest.annotation.Query;
import com.dtflys.forest.annotation.DataVariable;
import com.dtflys.forest.http.ForestResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;


import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 豆瓣服务实现类
 */
@Service
@Slf4j
public class DoubanServiceImpl implements IDoubanService {

    // Forest HTTP客户端接口
    public interface DoubanClient {
        // 旧的HTML抓取接口（保留作为注释）

//        @Request(
//            url = "https://search.douban.com/movie/subject_search",
//            type = "GET",
//            headers = {
//                "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
//                "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
//                "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
//                "Connection: keep-alive",
//                "Accept-Charset: utf-8"
//            },
//            charset = "utf-8",
//            contentType = "text/html; charset=utf-8"
//        )
//        ForestResponse<String> searchDouban(@Query("search_text") String query,
//                                           @Query("cat") String cat,
//                                           @Query("sort") String sort);



        // 新的豆瓣API接口 - 按照curl命令格式修改
        @Request(
            url = "https://api.douban.com/v2/movie/search",
            type = "POST",
            headers = {
                "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
                "Content-Type: application/json",
                "Accept: application/json"
            },
            dataType = "json",
            contentType = "application/json",
            data = "{\"q\": \"${q}\", \"start\": ${start}, \"count\": ${count}, \"apikey\": \"${apikey}\"}"
        )
        ForestResponse<Map> searchDoubanApi(@DataVariable("q") String q,
                                          @DataVariable("start") Integer start,
                                          @DataVariable("count") Integer count,
                                          @DataVariable("apikey") String apikey);

        @Request(
            url = "{url}",
            type = "GET",
            headers = {
                "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
                "Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8",
                "Referer: https://search.douban.com/"
            },
            dataType = "byte"
        )
        ForestResponse<byte[]> getImage(@DataVariable("url") String url);
        
        // 旧的豆瓣详情HTML抓取接口（保留作为注释）
//        @Request(
//            url = "https://movie.douban.com/subject/{id}/",
//            type = "GET",
//            headers = {
//                "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
//                "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
//                "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
//                "Connection: keep-alive",
//                "Accept-Charset: utf-8"
//            },
//            charset = "utf-8",
//            contentType = "text/html; charset=utf-8"
//        )
//        ForestResponse<String> getDoubanDetail(@DataVariable("id") String id);
        
        // 新的豆瓣动漫详情API接口 - 按照curl命令格式修改
        @Request(
            url = "https://api.douban.com/v2/movie/subject/${id}",
            type = "POST",
            headers = {
                "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
                "Content-Type: application/json",
                "Accept: application/json"
            },
            dataType = "json",
            contentType = "application/json",
            data = "{\"apikey\": \"${apikey}\"}"
        )
        ForestResponse<Map> getDoubanDetailApi(@DataVariable("id") String id,
                                             @DataVariable("apikey") String apikey);
    }

    @Override
    public Result<?> searchDoubanAnime(String query) {
        if (query == null || query.trim().isEmpty()) {
            return Result.fail("搜索关键词不能为空");
        }

        try {
            // 创建临时客户端实例
            DoubanClient client = com.dtflys.forest.Forest.client(DoubanClient.class);
            
            // 使用新的豆瓣API接口 - 按照curl命令格式修改参数名
            String apikey = "0ab215a8b1977939201640fa14c66bab"; // 豆瓣API密钥
            Integer start = 0;
            Integer count = 100;
            
            // 注意：参数名从query改为q，符合curl命令格式
            ForestResponse<Map> response = client.searchDoubanApi(query, start, count, apikey);

            if (!response.isSuccess()) {
                return Result.fail("获取豆瓣数据失败，状态码: " + response.getStatusCode());
            }

            // 获取API返回的JSON数据
            Map<String, Object> result = response.getResult();
            
            // 直接返回JSON数据，让前端进行解析
            return Result.success(result);
            
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("搜索失败，请稍后再试: " + e.getMessage());
        }
    }

    @Override
    public Result<byte[]> proxyImage(String url) {
        if (url == null || url.trim().isEmpty()) {
            return Result.fail("图片URL不能为空");
        }

        try {
            // 创建临时客户端实例
            DoubanClient client = com.dtflys.forest.Forest.client(DoubanClient.class);
            
            // 发起请求获取图片
            ForestResponse<byte[]> response = client.getImage(url);
            
            if (!response.isSuccess()) {
                return Result.fail("获取图片失败，状态码: " + response.getStatusCode());
            }
            
            return Result.success(response.getResult());
            
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("获取图片失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result<?> getDoubanDetail(String id) {
        if (id == null || id.trim().isEmpty()) {
            return Result.fail("动漫ID不能为空");
        }
        
        try {
            // 创建临时客户端实例
            DoubanClient client = com.dtflys.forest.Forest.client(DoubanClient.class);
            
            // 使用新的豆瓣详情API接口 - 按照curl命令格式添加apikey参数
            String apikey = "0ab215a8b1977939201640fa14c66bab"; // 豆瓣API密钥
            
            // 发起POST请求到豆瓣详情API
            ForestResponse<Map> response = client.getDoubanDetailApi(id, apikey);
            
            if (!response.isSuccess()) {
                return Result.fail("获取豆瓣详情失败，状态码: " + response.getStatusCode());
            }
            
            // 获取API返回的JSON数据
            Map<String, Object> result = response.getResult();
            
            // 将Map转换为JSON字符串返回，让前端进行解析
            // 使用Jackson或其他JSON库将Map转换为JSON字符串
            // 这里简单地使用toString()作为示例，实际项目中应使用JSON库
            return Result.success(result);
            
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("获取详情失败，请稍后再试: " + e.getMessage());
        }
    }

    /**
     * 解析豆瓣HTML搜索结果
     * @param html 豆瓣搜索返回的HTML内容
     * @return 动漫列表
     */
    private List<Map<String, Object>> parseDoubanHtml(String html) {
        List<Map<String, Object>> animeList = new ArrayList<>();
        
        try {
            // 使用正则表达式提取window.__DATA__对象
            Pattern pattern = Pattern.compile("window\\.__DATA__\\s*=\\s*(\\{.*?\\});", Pattern.DOTALL);
            Matcher matcher = pattern.matcher(html);
            
            if (matcher.find()) {
                String dataJson = matcher.group(1);
                // 这里简单返回HTML，让前端进行解析
                // 在实际项目中可以在后端进行JSON解析
            }
            
            // 备用方案：使用Jsoup解析HTML标签
            Document doc = Jsoup.parse(html);
            Elements items = doc.select(".item-root");
            
            for (int i = 0; i < items.size(); i++) {
                Element item = items.get(i);
                Map<String, Object> anime = new HashMap<>();
                
                // 提取基本信息
                String title = item.select(".title-text a").text();
                String abstractText = item.select(".abstract").text();
                String rating = item.select(".rating_nums").text();
                String coverUrl = item.select(".cover-link img").attr("src");
                
                // 提取年份
                int year = 2024;
                Pattern yearPattern = Pattern.compile("\\((\\d{4})\\)");
                Matcher yearMatcher = yearPattern.matcher(title);
                if (yearMatcher.find()) {
                    year = Integer.parseInt(yearMatcher.group(1));
                }
                
                // 只添加动画相关的内容
                if (abstractText != null && abstractText.contains("动画")) {
                    anime.put("id", System.currentTimeMillis() + i);
                    anime.put("title", title.replaceAll("\\s*\\(\\d{4}\\)$", ""));
                    anime.put("originalTitle", title);
                    anime.put("description", abstractText);
                    anime.put("rating", rating.isEmpty() ? 0 : Double.parseDouble(rating));
                    anime.put("coverImageUrl", coverUrl);
                    anime.put("year", year);
                    anime.put("releaseDate", year + "-01-01");
                    
                    animeList.add(anime);
                }
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return animeList;
    }
}